﻿using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Design;
using UnityEngine;
using UnityEngine.Tilemaps;

public class GameBoard : MonoBehaviour
{
    Vector2Int tileSize;
    public Tilemap LeftSceneMap = default;
    public Tilemap RightSceneMap = default;
    LogicTile[] leftLogicTiles = default;
    LogicTile[] rightLogicTiles = default;
    TileBase[] leftTiles = default;
    TileBase[] rightTiles = default;

    GameObject blockPrefab;
    GameObject bombPrefab;
    GameObject slimePrefab;
    GameObject energyPrefab;
    GameObject[] pastPrefabs;
    GameObject[] futurePrefabs;

    Vector2 modifyPlayer1 = new Vector2(-0.2f, -1.0f);
    Vector2 modifyPlayer2 = new Vector2(-0.5f, -1f);
    Vector2 modifyTerrian = new Vector2(0.5f, 0.5f);
    Vector2 modifyBomb = new Vector2(0.5f, 0.8f);

    GameObject leftScene;
    GameObject rightScene;

    private float energyGap = 15f;

    private void Awake()
    {
        var leftBounds = LeftSceneMap.cellBounds;
        var rithtBounds = RightSceneMap.cellBounds;                
        leftTiles = LeftSceneMap.GetTilesBlock(leftBounds);
        rightTiles = RightSceneMap.GetTilesBlock(leftBounds);
        leftLogicTiles = new LogicTile[LeftSceneMap.size.x * LeftSceneMap.size.y];
        for (int i = 0; i < LeftSceneMap.size.x * LeftSceneMap.size.y; ++i) {
            leftLogicTiles[i] = new LogicTile();
        }
        rightLogicTiles = new LogicTile[RightSceneMap.size.x * RightSceneMap.size.y];
        for (int i = 0; i < RightSceneMap.size.x * RightSceneMap.size.y; ++i) {
            rightLogicTiles[i] = new LogicTile();
        }        

        int index = 0;
        foreach (var pos in LeftSceneMap.cellBounds.allPositionsWithin)
        {            
            leftLogicTiles[index].tileBase = leftTiles[index];
            leftLogicTiles[index].pos = pos;                        
            index++;
        }
        index = 0;
        foreach (var pos in RightSceneMap.cellBounds.allPositionsWithin)
        {            
            rightLogicTiles[index].tileBase = rightTiles[index];
            rightLogicTiles[index].pos = pos;
            index++;
        }

        var posList = LeftSceneMap.cellBounds.allPositionsWithin;

        pastPrefabs = new GameObject[3];
        futurePrefabs = new GameObject[3];
        pastPrefabs[0] = Resources.Load("Prefabs/Map/iron_block") as GameObject;
        futurePrefabs[0] = pastPrefabs[0];
        pastPrefabs[1] = Resources.Load("Prefabs/Map/Past/past_water") as GameObject;
        futurePrefabs[1] = Resources.Load("Prefabs/Map/Future/future_water") as GameObject;
        pastPrefabs[2] = Resources.Load("Prefabs/Map/Past/past_tree") as GameObject;
        futurePrefabs[2] = Resources.Load("Prefabs/Map/Future/future_tree") as GameObject;

    }

    // Start is called before the first frame update
    void Start()
    {
        //blockPrefab = Resources.Load("Prefabs/block") as GameObject;
        bombPrefab = Resources.Load("Prefabs/Bomb") as GameObject;
        slimePrefab = Resources.Load("Prefabs/Map/slime") as GameObject;
        energyPrefab = Resources.Load("Prefabs/Map/Energy") as GameObject;

        leftScene = GameObject.Find("LeftScene");
        rightScene = GameObject.Find("RightScene");

        Mapinitialize();
    }

    Vector2[] blocks = { new Vector2(0, 10), new Vector2(-11, 0), new Vector2(-7, 4), new Vector2(10, -3), new Vector2(-4, -2), new Vector2(-13, -7), new Vector2(8, -7), new Vector2(2, -8), new Vector2(-1, -10), new Vector2(11, -12), new Vector2(8, -13), };
    Vector2[] trees = { new Vector2(0, 0),new Vector2(1, 1),new Vector2(2, 1),new Vector2(3, 0),new Vector2(8, 0),new Vector2(9, 3),new Vector2(10, 3),new Vector2(11, 4),new Vector2(11, -3),new Vector2(13, -3),new Vector2(8, -5),new Vector2(9, -5),new Vector2(7, -11),new Vector2(0, -11),new Vector2(-1, -13),new Vector2(-2, -13),new Vector2(-1, -4),new Vector2(-2, -4),new Vector2(-2, -5),new Vector2(-3, 0),new Vector2(-4, 1),new Vector2(-7, 1),new Vector2(-6, 0),new Vector2(-6, -1),new Vector2(-6, -2),new Vector2(-6, -8),new Vector2(-8, -8),new Vector2(-9, -10),new Vector2(-9, -5),new Vector2(-12, -4),new Vector2(-13, -5),new Vector2(-13, -10),new Vector2(-14, 1),new Vector2(-14, -11),new Vector2(-14, -7),new Vector2(-11, 11),new Vector2(-9, 7),new Vector2(9, 11),new Vector2(10, 11),new Vector2(11, 9),new Vector2(9, 14) };
    Vector2[] waters = { new Vector2(1, 2), new Vector2(1, 3), new Vector2(2, 2), new Vector2(2, 3), new Vector2(3, 2), new Vector2(3, 3), new Vector2(3, 1), new Vector2(4, 1), new Vector2(4, 0), new Vector2(4, -1), new Vector2(3, -1), new Vector2(3, -2), new Vector2(4, -2), new Vector2(4, -3), new Vector2(5, -3), new Vector2(5, -4), new Vector2(8, -4), new Vector2(9, -4), new Vector2(10, -4), new Vector2(11, -4), new Vector2(12, -4), new Vector2(13, -4), new Vector2(1, -2), new Vector2(1, -3), new Vector2(0, -2), new Vector2(0, -3), new Vector2(-1, -2), new Vector2(-1, -3), new Vector2(-2, -2), new Vector2(-2, -3), new Vector2(-3, -1), new Vector2(-3, -2), new Vector2(-3, -3), new Vector2(-3, -4), new Vector2(-3, -5), new Vector2(-4, 0), new Vector2(-4, -1), new Vector2(-5, 0), new Vector2(-5, 1), new Vector2(-5, 2), new Vector2(-6, 0), new Vector2(-4, 2), new Vector2(-4, 3), new Vector2(-3, 2), new Vector2(-3, 3), new Vector2(-3, 4), new Vector2(-2, 2), new Vector2(-2, 3), new Vector2(-2, 4), new Vector2(-6, -5), new Vector2(-6, -6), new Vector2(-6, -7), new Vector2(-7, -6), new Vector2(-7, -7), new Vector2(-7, -8), new Vector2(-7, -9), new Vector2(-8, -6), new Vector2(-8, -7), new Vector2(-7, -11), new Vector2(-7, -12), new Vector2(-8, -11), new Vector2(-8, -12), new Vector2(-8, -13), new Vector2(-9, -13) };

    void Mapinitialize()
    {
        int nowtype = 0;
        foreach(Vector2 pos in blocks)
        {
            buildBlock(pos, nowtype);
        }
        nowtype = 2;
        foreach (Vector2 pos in trees)
        {
            buildBlock(pos, nowtype);
        }
        nowtype = 1;
        foreach (Vector2 pos in waters)
        {
            buildBlock(pos, nowtype);
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (energyGap > 0)
        {
            energyGap -= Time.deltaTime;
        }
        else {
            for (int i = 0; i < 3; ++i)
            {
                int targetIndex = Random.Range(0, 28 * 28);
                if (rightLogicTiles[targetIndex].terr == null)
                {
                    GameObject energy = Instantiate(energyPrefab);
                    energy.transform.parent = rightScene.transform;
                    energy.transform.localPosition = new Vector3(rightLogicTiles[targetIndex].pos.x + modifyTerrian.x, rightLogicTiles[targetIndex].pos.y + modifyTerrian.y, rightLogicTiles[targetIndex].pos.z);
                }

            }
            
            energyGap = 10f;            
        }
        
    }

    public void removeBlock(Vector3 targetPos) {
        int targetIndex = 0;
        float dist = 10000000;
        for (int i = 0; i < leftLogicTiles.Length; ++i)
        {
            var pos = leftLogicTiles[i].pos;
            float deltaX = pos.x - (targetPos.x);
            float deltaY = pos.y - (targetPos.y);
            float tempDist = deltaX * deltaX + deltaY * deltaY;
            if (tempDist < dist)
            {
                targetIndex = i;
                dist = tempDist;
            }
        }
        if (leftLogicTiles[targetIndex].terr != null)
        {
            Destroy(leftLogicTiles[targetIndex].terr);
        }
        if (rightLogicTiles[targetIndex].terr != null) {
            Destroy(rightLogicTiles[targetIndex].terr);
        }
    }

    public void buildBlock(Vector3 playerPos, int type) {
        int targetIndex = 0;        
        float dist = 10000000;                
        for (int i = 0; i < leftLogicTiles.Length; ++i)
        {            
            var pos = leftLogicTiles[i].pos;
            float deltaX = pos.x - (playerPos.x + modifyPlayer1.x);
            float deltaY = pos.y - (playerPos.y + modifyPlayer1.y);
            float tempDist = deltaX * deltaX + deltaY * deltaY;
            if (tempDist < dist)
            {                
                targetIndex = i;
                dist = tempDist;
            }
        }
        if (leftLogicTiles[targetIndex].terr == null) {
            GameObject block = Instantiate(pastPrefabs[type]);
            block.transform.parent = leftScene.transform;
            block.transform.localPosition = new Vector3(leftLogicTiles[targetIndex].pos.x + modifyTerrian.x, leftLogicTiles[targetIndex].pos.y + modifyTerrian.y, leftLogicTiles[targetIndex].pos.z);
            leftLogicTiles[targetIndex].terr = block;

            if (rightLogicTiles[targetIndex] != null)
            {
                GameObject futureblock = Instantiate(futurePrefabs[type]);
                futureblock.transform.parent = rightScene.transform;
                futureblock.transform.localPosition = new Vector3(rightLogicTiles[targetIndex].pos.x + modifyTerrian.x, rightLogicTiles[targetIndex].pos.y + modifyTerrian.y, rightLogicTiles[targetIndex].pos.z);
                rightLogicTiles[targetIndex].terr = futureblock;
            }
        }        
    }

    public void setSlime(Vector3 targetPos) {
        int targetIndex = 0;
        float dist = 10000000;
        for (int i = 0; i < rightLogicTiles.Length; ++i)
        {
            var pos = leftLogicTiles[i].pos;
            float deltaX = pos.x - (targetPos.x);
            float deltaY = pos.y - (targetPos.y);
            float tempDist = deltaX * deltaX + deltaY * deltaY;
            if (tempDist < dist)
            {
                targetIndex = i;
                dist = tempDist;
            }
        }
        if (rightLogicTiles[targetIndex].terr == null)
        {
            GameObject block = Instantiate(slimePrefab);            

            block.transform.parent = rightScene.transform;
            block.transform.localPosition = new Vector3(rightLogicTiles[targetIndex].pos.x + modifyTerrian.x, rightLogicTiles[targetIndex].pos.y + modifyTerrian.y, rightLogicTiles[targetIndex].pos.z);
            //rightLogicTiles[targetIndex].terr = block;            
        }
    }

    public void buildBomb(Transform player) {        
        int targetIndex = 0;
        float dist = 10000000;
        for (int i = 0; i < rightLogicTiles.Length; ++i)
        {
            var pos = rightLogicTiles[i].pos;
            //Debug.Log(pos);
            float deltaX = pos.x - (player.localPosition.x + modifyPlayer2.x);
            float deltaY = pos.y - (player.localPosition.y + modifyPlayer2.y);
            float tempDist = deltaX * deltaX + deltaY * deltaY;
            if (tempDist < dist)
            {
                targetIndex = i;
                dist = tempDist;
            }
        }
        //Debug.Log(rightLogicTiles[targetIndex].pos);
        if (rightLogicTiles[targetIndex].terr == null)
        {
            GameObject bomb = Instantiate(bombPrefab);            

            bomb.transform.parent = rightScene.transform;
            bomb.transform.localPosition = new Vector3(rightLogicTiles[targetIndex].pos.x + modifyBomb.x, rightLogicTiles[targetIndex].pos.y + modifyBomb.y, rightLogicTiles[targetIndex].pos.z);
            //leftLogicTiles[targetIndex].terr = bomb;            
        }
    }
}

